package love.contact.data;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import love.contact.R;
import love.contact.engine.ContactIconOperateDelegate;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import wwk.common.sqlite.SqliteUtil;
import wwk.common.util.DateTimeUtil;
import android.content.Context;
import android.database.Cursor;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.util.Log;
import android.util.Xml;

public class PhoneBook {
	private SqliteUtil sqliteUtil;
	private int referenceCount;
	
	public PhoneBook()
	{
		sqliteUtil=new SqliteUtil();
	}
	
	public SqliteUtil getSqliteUtil() {
		return sqliteUtil;
	}
	
	public void openOrCreateDatabase(Context context)
	{
		boolean bool=sqliteUtil.openOrCreateDatabase(context, "ilovecontact_database.db");
		if(bool)
		{
			Group.createTable(sqliteUtil);
		}
	}
	
	public void openOrCreateDatabaseWithReferenceCount(Context context)
	{
		boolean bool=sqliteUtil.openOrCreateDatabase(context, "ilovecontact_database.db");
		if(bool)
		{
			Group.createTable(sqliteUtil);
		}
		referenceCount++;
	}
	
	public void closeDatabase()
	{
		referenceCount--;
		if(referenceCount<=0)
		{
			sqliteUtil.close();
		}
	}

	public String export(Context context,Handler handler,ContactIconOperateDelegate delegate)
	{
		//pull parser
		String content=null;
		
		StringWriter writer = new StringWriter();
		XmlSerializer serializer = Xml.newSerializer();

	   	try 
	   	{
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
				
			serializer.startTag("", "phonebook");
			
			int groupCount=Group.groupCount(sqliteUtil);
			int contactCount=Contact.contactCount(context);
			
			Message msg=new Message();
			msg.what=ContactConst.MSG_EXPORT_INIT;
			msg.arg1=groupCount+contactCount;
			handler.sendMessage(msg);

			serializer.attribute("", "datetime", DateTimeUtil.getNow());
			serializer.attribute("", "group_count", ""+groupCount);
			serializer.attribute("", "contact_count", ""+contactCount);
			
			//groups
			Group.export(serializer, sqliteUtil,handler);
		   	
		   	//contacts
			serializer.startTag("", "contacts");
			Contact.export(context, serializer,handler,delegate);
			serializer.endTag("", "contacts");
			
			serializer.endTag("", "phonebook");
		    serializer.endDocument();
		    
		    content = writer.toString();
		} 
	   	catch (IllegalArgumentException e) 
	   	{
			e.printStackTrace();
		} 
	   	catch (IllegalStateException e) 
	   	{
			e.printStackTrace();
		} 
	   	catch (IOException e) 
	   	{
			e.printStackTrace();
		}

		return content;
	}

	static public String getImportFileInfo(Context context,InputStream inputStream,String filePathName)
	{
		StringBuffer buffer=new StringBuffer();

		if(inputStream!=null)
		{
			XmlPullParser parser=Xml.newPullParser();
			try 
			{
				parser.setInput(inputStream,"UTF-8");
	
		        int eventType = parser.getEventType();
				while (eventType != XmlPullParser.END_DOCUMENT) 
				{
					if (eventType == XmlPullParser.START_TAG) 
					{
						String tagName=parser.getName();
						if(tagName.equals("phonebook"))
						{
							String datetime=null;
							String groupCount=null;
							String contactCount=null;
	
							int attributeCount=parser.getAttributeCount();
							for(int i= 0; i < attributeCount;i++)
							{
								String attributeName=parser.getAttributeName(i);
								String attributeValue=parser.getAttributeValue(i);
								
								if(attributeName.equals("datetime"))
								{
									datetime=attributeValue;
								}
								else if(attributeName.equals("group_count"))
								{
									groupCount=attributeValue;
								}
								else if(attributeName.equals("contact_count"))
								{
									contactCount=attributeValue;
								}
							}
							
							buffer.append(context.getString(R.string.createDatetime)+(datetime==null?context.getString(R.string.unknow):datetime));
							buffer.append("\n"+context.getString(R.string.groupCount)+(groupCount==null?context.getString(R.string.unknow):groupCount));
							buffer.append("\n"+context.getString(R.string.contactCount)+(contactCount==null?context.getString(R.string.unknow):contactCount));
							
							break;
						}
					}
									
					eventType = parser.next();
				}//end while
			} 
			catch (XmlPullParserException e) 
			{ 
				e.printStackTrace();
			}
			catch (IOException e) 
			{ 
				e.printStackTrace();
			}
		}
		
		buffer.append("\n"+context.getString(R.string.filePath)+filePathName);
		
		return buffer.toString();
	}
	
	//return if import success
	public boolean importe(Context context,InputStream contactsFileInputStream,InputStream iconsFileInputStream,Handler handler)
	{
		boolean importeResult=false;

		XmlPullParser parser=Xml.newPullParser();
		try 
		{
			parser.setInput(contactsFileInputStream,"UTF-8");

			Map<Integer,String> contactGroupMap=new HashMap<Integer,String>();
			
	        int eventType = parser.getEventType();
			while (eventType != XmlPullParser.END_DOCUMENT) 
			{
				if (eventType == XmlPullParser.START_TAG) 
				{
					String tagName=parser.getName();
					
					if(tagName.equals("phonebook"))
					{
						int groupCount=0;
						int contactCount=0;
						
						int attributeCount=parser.getAttributeCount();
						for(int i= 0; i < attributeCount;i++)
						{
							String attributeName=parser.getAttributeName(i);
							String attributeValue=parser.getAttributeValue(i);
							
							if(attributeName.equals("group_count"))
							{
								groupCount=Integer.parseInt(attributeValue);
							}
							else if(attributeName.equals("contact_count"))
							{
								contactCount=Integer.parseInt(attributeValue);
							}
						}
						
						Message msg=new Message();
						msg.what=ContactConst.MSG_IMPORT_INIT;
						msg.arg1=groupCount+contactCount;
						handler.sendMessage(msg);
						
						//can not do delete until find phonebook node
						if(groupCount+contactCount>0)
						{
							Group.deleteAll(sqliteUtil);
							Contact.deleteAll(context);
							
							importeResult=true;
						}
						else
						{
							//exists parser
							//break;  //for symbian version
						}
					}
					else if(tagName.equals("group"))
					{
						String groupId=null;
						String groupName=null;

						int attributeCount=parser.getAttributeCount();
						for(int i= 0; i < attributeCount;i++)
						{
							String attributeName=parser.getAttributeName(i);
							String attributeValue=parser.getAttributeValue(i);
							
							if(attributeName.equals("id"))
							{
								groupId=attributeValue;
							}
							else if(attributeName.equals("name"))
							{
								groupName=attributeValue;
							}
						}
						
						Group.insert(sqliteUtil, groupId, groupName);

						Log.d("group", groupName+"parse finished");
						
						handler.sendEmptyMessage(ContactConst.MSG_IMPORT_INCREASE);
					}
					else if(tagName.equals("contact_group_item"))
					{
						String groupId=null;
						int contactId=0;

						int attributeCount=parser.getAttributeCount();
						for(int i= 0; i < attributeCount;i++)
						{
							String attributeName=parser.getAttributeName(i);
							String attributeValue=parser.getAttributeValue(i);
							
							if(attributeName.equals("group_id"))
							{
								groupId=attributeValue;
							}
							else if(attributeName.equals("contact_id"))
							{
								contactId=Integer.parseInt(attributeValue);
							}
						}
						
						contactGroupMap.put(contactId, groupId);
					}
					else if(tagName.equals("contact"))
					{
						//new add contact
						Contact contact=new Contact();
						contact.parse(context,parser);
						int oldContactId=contact.getId();
						boolean ret=contact.insert(context,iconsFileInputStream);//
						if(ret)
						{
							String groupId=contactGroupMap.get(oldContactId);
							if(groupId!=null && groupId.length()>0)
							{
								//create a new contactid
								int newContactId=contact.getId();
								Group.insertContactGroup(sqliteUtil, groupId, newContactId);
							}
							contactGroupMap.remove(oldContactId);
						}
						
						Log.d("contact",contact.getDisplayName()+" parse finished");
						
						handler.sendEmptyMessage(ContactConst.MSG_IMPORT_INCREASE);
					}
				}//end XmlPullParser.START_TAG
								
				eventType = parser.next();
			}//end while
			
			if(contactsFileInputStream!=null)
			{
				contactsFileInputStream.close();//iconsFileInputStream,
			}
			
			if(iconsFileInputStream!=null)
			{
				iconsFileInputStream.close();//iconsFileInputStream,
			}
			
			Log.d("PhoneBook","import finished");
		} 
		catch (XmlPullParserException e) 
		{ 
			e.printStackTrace();
		}
		catch (IOException e) 
		{ 
			e.printStackTrace();
		}
		
		return importeResult;
	}
	
	public Object[] getContactInfo(Context context,String number)
	{
		Object[] objs=new Object[2];
		Contact contact=PhoneBook.getContact(context, number);
		if(contact!=null)
		{
			objs[0]=contact;
			
			long id=contact.getId();
			String selection=String.format("contactId=%d",id);
			Cursor cursor=sqliteUtil.query("contact_group",null,selection,null,null,null,null);

			if(cursor.moveToNext())
			{
				String groupId=cursor.getString(cursor.getColumnIndex("groupId"));
				String groupName=Group.getLongName(sqliteUtil, groupId, "-");
				objs[1]=groupName;
			}
			
			cursor.close();
		}
		
		return objs;
	}
	
	static public Contact getContact(Context context,String number)
	{
		Contact contact=null;
		
		String[] projection = {ContactsContract.CommonDataKinds.Phone.CONTACT_ID};

		Cursor cursor = context.getContentResolver().query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
				projection,    // Which columns to return.
                ContactsContract.CommonDataKinds.Phone.NUMBER + " = '" + number + "'", // WHERE clause.
                null,          // WHERE clause value substitution
                null);   // Sort order.

		if(cursor!=null && cursor.moveToNext())
		{
			int contactId=cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.CONTACT_ID)); 
			
			String[] projection2 = {ContactsContract.PhoneLookup.DISPLAY_NAME};
			
			Cursor cursor2 = context.getContentResolver().query(
					ContactsContract.Contacts.CONTENT_URI,
					projection2,    // Which columns to return.
					ContactsContract.Contacts._ID + " =" + contactId , // WHERE clause.
	                null,          // WHERE clause value substitution
	                null);   // Sort order.

			if(cursor2!=null && cursor2.moveToNext())
			{
				contact=new Contact();
				String name=cursor2.getString(cursor2.getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME)); 
				contact.setId(contactId);
				contact.setDisplayName(name);
			}
			
			cursor2.close();
		}
		
		cursor.close();
		
		return contact;
	}
}